package com.jwds.digital.bios.business.service.service.belt.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.FiveDefenseCount;
import com.jwds.digital.bios.business.core.infrastructure.vo.feign.BasicDeviceRespVO;
import com.jwds.digital.bios.business.core.constants.BeltCloudConstant;
import com.jwds.digital.bios.business.core.exceptions.RecordNotFoundException;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.BeltProtectionStatusReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.dto.belt.assembler.BeltProtectionStatusAssembler;
import com.jwds.digital.bios.business.core.infrastructure.dto.feign.BasicDeviceReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.dto.feign.FlowBasicReqDTO;
import com.jwds.digital.bios.business.core.infrastructure.dto.feign.model.DeviceStatusDTO;
import com.jwds.digital.bios.business.core.infrastructure.entity.belt.BeltProtectionStatus;
import com.jwds.digital.bios.business.core.infrastructure.mapper.belt.BeltProtectionStatusMapper;
import com.jwds.digital.bios.business.core.infrastructure.telegram.BeltRouteBelongData;
import com.jwds.digital.bios.business.core.infrastructure.vo.belt.BeltProtectionStatusRespVO;
import com.jwds.digital.bios.business.core.infrastructure.vo.feign.BasicDeviceRespVO;
import com.jwds.digital.bios.business.core.infrastructure.vo.feign.FlowBasicRespVO;
import com.jwds.digital.bios.business.rpc.feign.BasicDeviceFeign;
import com.jwds.digital.bios.business.rpc.feign.FlowBasicFeign;
import com.jwds.digital.bios.business.rpc.feign.RealTimeDataFeign;
import com.jwds.digital.bios.business.service.service.belt.IBeltProtectionStatusService;
import com.jwds.tdc.framework.application.lib.page.PageRequest;
import com.jwds.tdc.framework.application.lib.page.PageResponse;

import java.time.LocalDateTime;
import java.util.Collections;
import com.jwds.tdc.framework.cache.service.CacheService;
import com.netflix.config.util.ConfigurationUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 五防健康状态实现类
 * @author 林柏云
 * @date 2024-10-24
 */
@Slf4j
@Service
public class BeltProtectionStatusServiceImpl extends ServiceImpl<BeltProtectionStatusMapper, BeltProtectionStatus> implements IBeltProtectionStatusService {

  @Autowired
  private BeltProtectionStatusMapper baseMapper;

  @Resource
  CacheService cacheService;

  @Resource
  FlowBasicFeign flowBasicFeign;

  @Resource
  BasicDeviceFeign basicDeviceFeign;

  @Resource
  RealTimeDataFeign realTimeDataFeign;

  @Override
  public BeltProtectionStatusRespVO queryById(Long id) {
    if(id == null) {
      return null;
    }
    BeltProtectionStatus entity = baseMapper.selectById(id);
    return BeltProtectionStatusAssembler.entity2dto(entity);
  }

  @Override
  public PageResponse<BeltProtectionStatusRespVO> page(PageRequest<BeltProtectionStatusReqDTO> request) {
    BeltProtectionStatusReqDTO condition = request.getQueryCondition();
    Page<BeltProtectionStatusRespVO> page = new Page<>(request.getPageIndex(), request.getPageSize());
    IPage<BeltProtectionStatusRespVO> pageData = baseMapper.pageQuery(page, condition);
    return new PageResponse<>((Page<?>)pageData, pageData.getRecords());
  }

  @Override
  public List<BeltProtectionStatusRespVO> list(BeltProtectionStatusReqDTO reqDto) {
    return baseMapper.queryList(reqDto);
  }

  @Override
  public void add(BeltProtectionStatusReqDTO reqDto) {
    BeltProtectionStatus entity = BeltProtectionStatusAssembler.dto2entity(reqDto);
    baseMapper.insert(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchAdd(List<BeltProtectionStatusReqDTO> dtoList) {
    dtoList.forEach(this::add);
  }

  @Override
  public void update(BeltProtectionStatusReqDTO reqDto) {
    BeltProtectionStatus oldEntity = baseMapper.selectById(reqDto.getId());
    if (oldEntity == null) {
      throw new RecordNotFoundException();
    }
    BeltProtectionStatus newEntity = BeltProtectionStatusAssembler.dto2entity(reqDto, oldEntity);
    baseMapper.updateById(newEntity);
  }

  @Override
  public void delete(Long id) {
    BeltProtectionStatus oldEntity = baseMapper.selectById(id);
    if (oldEntity == null) {
      throw new RecordNotFoundException();
    }
    baseMapper.deleteById(id);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchDelete(List<Long> ids) {
    for (Long id : ids) {
      delete(id);
    }
  }

  @Override
  public List<FiveDefenseCount> groupByBeltId(List<BasicDeviceRespVO> beltList, LocalDateTime startTime, LocalDateTime endTime) {
    return baseMapper.groupByBeltId(beltList, startTime, endTime);
  }

  @Override
  public void queryDeviceStatusDataMap() {

    Set<String> keys = cacheService.getKeys(BeltCloudConstant.BC_RUNNING_ROUTE_KEY + "*");
    Map<String, BeltRouteBelongData> keyToBeltRouteBelongDataMap = new HashMap<>();

    // 构建 key 到 BeltRouteBelongData 的映射
    for (String key : keys) {
      String beltRouteBelongData = cacheService.getString(key);
      keyToBeltRouteBelongDataMap.put(key, JSONUtil.toBean(beltRouteBelongData,BeltRouteBelongData.class));
    }

    // 批量获取所有基础设备信息
    List<BasicDeviceRespVO> allBasicDevices = basicDeviceFeign.list(new BasicDeviceReqDTO()).getData();

    // 收集所有匹配的皮带信息Code
    List<String> beltList = keys.stream().map(key -> {
      BeltRouteBelongData beltRouteBelongData = keyToBeltRouteBelongDataMap.get(key);
      FlowBasicReqDTO flowBasicReqDTO = new FlowBasicReqDTO().setFlowNo(beltRouteBelongData.getFlowNo());
      FlowBasicRespVO flowBasicRespVO = flowBasicFeign.all(flowBasicReqDTO).getData().get(0);
      List<String> beltCodes = Arrays.asList(flowBasicRespVO.getFlowCode().split("_"));
      return allBasicDevices.stream().filter(basicDeviceRespVO -> beltCodes.contains(basicDeviceRespVO.getDeviceCode())).map(BasicDeviceRespVO::getDeviceCode).collect(Collectors.toList());
    }).flatMap(List::stream).distinct().collect(Collectors.toList());

    // 查询所有皮带代码的设备状态数据
    Map<String, DeviceStatusDTO> deviceStatusMap = realTimeDataFeign.queryDeviceStatusDataMap(beltList).getData();

    beltList.stream()
            .filter(deviceStatusMap::containsKey)
            .map(beltCode -> new AbstractMap.SimpleEntry<>(beltCode, deviceStatusMap.get(beltCode)))
            .filter(entry -> hasAnyTrue(entry.getValue()))
            .map(entry -> deviceStatusMap.put(entry.getKey(), entry.getValue()))
            .collect(Collectors.toList());

    List<BeltProtectionStatusReqDTO> beltProtectionStatusReqDTOList = new ArrayList<>();
    deviceStatusMap.forEach((key, value) -> {
      BeltProtectionStatusReqDTO beltProtectionStatusReqDTO = new BeltProtectionStatusReqDTO();

      Boolean ropeValue = value.getRope1() != null ? value.getRope1() : value.getRope2();
      beltProtectionStatusReqDTO.setRopeStatus(convertBooleanToInt(ropeValue));
      beltProtectionStatusReqDTO.setBlockStatus(convertBooleanToInt(value.getClog()));
      beltProtectionStatusReqDTO.setTearStatus(convertBooleanToInt(value.getTear()));
      beltProtectionStatusReqDTO.setSevereDeviationStatus(convertBooleanToInt(value.getOfftrack()));
      beltProtectionStatusReqDTO.setMinorDeviationStatus(convertBooleanToInt(value.getMildOfftrack()));
      beltProtectionStatusReqDTO.setSlipStatus(convertBooleanToInt(value.getSlip()));
      beltProtectionStatusReqDTO.setCollectionTime(LocalDateTime.now());
      BeltRouteBelongData beltRouteBelongData = keyToBeltRouteBelongDataMap.get(key);
      beltProtectionStatusReqDTO.setRouteId(beltRouteBelongData.getFlowNo().longValue());
      beltProtectionStatusReqDTO.setTaskId(beltRouteBelongData.getTaskId());

      beltProtectionStatusReqDTOList.add(beltProtectionStatusReqDTO);
    });

    this.batchAdd(beltProtectionStatusReqDTOList);

  }

  // 定义一个方法来检查 DeviceStatusDTO 中是否有任何布尔值字段为 true
  private static boolean hasAnyTrue(DeviceStatusDTO deviceStatus) {
    return Boolean.TRUE.equals(deviceStatus.getRope1()) || Boolean.TRUE.equals(deviceStatus.getRope2()) || Boolean.TRUE.equals(deviceStatus.getOfftrack()) || Boolean.TRUE.equals(deviceStatus.getMildOfftrack()) || Boolean.TRUE.equals(deviceStatus.getClog()) || Boolean.TRUE.equals(deviceStatus.getTear()) || Boolean.TRUE.equals(deviceStatus.getSlip());
  }

  // 布尔值转换
  private static Integer convertBooleanToInt(Boolean bool) {
    return bool != null && bool ? 1 : 0;
  }

}
